using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Microsoft.Dss.Core.Attributes;
using System.Diagnostics;

namespace VEXRobotics
{

    /// <summary>
    /// The standard return package in which all return messages inherit from
    /// </summary>
    [DataContract]
    [Description("VEX command return value.")]
    public class VEXResponse : VEXCommand
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        public VEXResponse()
        {
        }

        /// <summary>
        /// Initializing constructor
        /// </summary>
        /// <param name="command">Command executed</param>
        /// <param name="dataLength">Length of the response data</param>
        public VEXResponse(VEXHelper.VEXCommandCode command, int dataLength)
            : base(command, dataLength)
        {
        }

        /// <summary>
        /// Initializing constructor
        /// </summary>
        /// <param name="command">Command executed</param>
        /// <param name="dataLength">Length of the response data</param>
        /// <param name="data">Data returned</param>
        public VEXResponse(VEXHelper.VEXCommandCode command, int dataLength, byte[] data)
            : base(command, dataLength, data)
        {
        }

        /// <summary>
        /// Status of the command
        /// </summary>
        [DataMember]
        public int Status
        {
            get
            {
                if (Data != null && Data.Length >= 1)
                    return Data[0];
                return -1;
            }
            set
            {
                if (Data.Length >= 1)
                    Data[0] = (byte)value;
            }
        }

        /// <summary>
        /// Error status codes
        /// </summary>
        [DataContract]
        [Description("VEX Error Code")]
        public enum VEXErrorCode : byte
        {
            /// <summary>
            /// Command succeeded
            /// </summary>
            Success = 0x00,

            /// <summary>
            /// Unknown whether it succeeded
            /// </summary>
            UnknownStatus = 0x80,

            /// <summary>
            /// An error occured
            /// </summary>
            UndefinedError = 0x81,
        }

        /// <summary>
        ///  See if there was an error
        /// </summary>
        [DataMember]
        [Description("The error code returned.")]
        public VEXErrorCode ErrorCode
        {
            get
            {
                if (Data != null && Data.Length >= 1)
                {
                    try
                    {
                        return (VEXErrorCode)Data[0];
                    }
                    catch
                    {
                        Debug.WriteLine("Unknown VEX Return code: " + Data[0].ToString());
                        return VEXErrorCode.UnknownStatus;
                    }
                }
                return VEXErrorCode.UnknownStatus;
            }
            set
            {
                if (Data.Length >= 1)
                    Data[0] = (byte)value;
            }
        }
    }

    /// <summary>
    /// An exception was generated during communications
    /// </summary>
    [DataContract]
    public class VEXResponseException : VEXResponse
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        public VEXResponseException()
            : base(0, 0) { }

        /// <summary>
        /// Initializing constructor
        /// </summary>
        /// <param name="cmd">Command executed</param>
        /// <param name="ex">Exception generated</param>
        public VEXResponseException(VEXCommand cmd, Exception ex)
            : base(cmd.VEXCommandCode, 0)
        {
            this.Data = VEXHelper.StringToData(ex.Message, ex.Message.Length + 1);
        }

        /// <summary>
        /// Initializing constructor
        /// </summary>
        /// <param name="cmd">Command executed</param>
        /// <param name="errorMessage">Error message</param>
        public VEXResponseException(VEXCommand cmd, string errorMessage)
            : base(cmd.VEXCommandCode, 0)
        {
            this.Data = VEXHelper.StringToData(errorMessage, errorMessage.Length + 1);
        }

        /// <summary>
        /// Error message
        /// </summary>
        [DataMember]
        [Description("The error message text string.")]
        public string ErrorMessage
        {
            get
            {
                if (Data == null || Data.Length < 2)
                    return string.Empty;

                return VEXHelper.DataToString(Data, 0);
            }

            set
            {
                this.Data = VEXHelper.StringToData(value, value.Length + 1);
            }
        }
    }
}
